package main

import (
	"fmt"
	"os"
	"strconv"
	"strings"
)

// generateCombinations generates all unique combinations of 4 numbers from 1-13
func generateCombinations() [][]int {
	var combinations [][]int
	// Generate combinations with 4 nested loops
	for i := 1; i <= 13; i++ {
		for j := i; j <= 13; j++ {
			for k := j; k <= 13; k++ {
				for l := k; l <= 13; l++ {
					combinations = append(combinations, []int{i, j, k, l})
				}
			}
		}
	}
	return combinations
}

// canMake24 checks if a combination of 4 numbers can make 24 using basic operations
func canMake24(nums []int) bool {
	return find24(float64(nums[0]), float64(nums[1]), float64(nums[2]), float64(nums[3]))
}

// find24 recursively tries all combinations of operations to make 24
func find24(a, b, c, d float64) bool {
	// Try all combinations of the four numbers with all operations
	return testOperations([]float64{a, b, c, d})
}

// testOperations recursively tests all possible operation combinations
func testOperations(nums []float64) bool {
	if len(nums) == 1 {
		// Check if we got 24 (with small epsilon for floating point comparison)
		return abs(nums[0]-24) < 1e-6
	}

	// Try combining each pair of numbers with all operations
	for i := 0; i < len(nums); i++ {
		for j := i + 1; j < len(nums); j++ {
			// Create a new slice without the two selected numbers
			remaining := []float64{}
			for k := 0; k < len(nums); k++ {
				if k != i && k != j {
					remaining = append(remaining, nums[k])
				}
			}

			a, b := nums[i], nums[j]

			// Try all operations
			// Addition
			if testOperations(append(remaining, a+b)) {
				return true
			}

			// Multiplication
			if testOperations(append(remaining, a*b)) {
				return true
			}

			// Subtraction (a-b)
			if testOperations(append(remaining, a-b)) {
				return true
			}

			// Subtraction (b-a)
			if testOperations(append(remaining, b-a)) {
				return true
			}

			// Division (a/b) if b is not zero
			if b != 0 {
				if testOperations(append(remaining, a/b)) {
					return true
				}
			}

			// Division (b/a) if a is not zero
			if a != 0 {
				if testOperations(append(remaining, b/a)) {
					return true
				}
			}
		}
	}

	return false
}

// abs returns the absolute value
func abs(x float64) float64 {
	if x < 0 {
		return -x
	}
	return x
}

// generateAndSaveQuestions generates all valid questions and saves them to a file
func generateAndSaveQuestions() error {
	file, err := os.Create("data/24point_questions.txt")
	if err != nil {
		return fmt.Errorf("failed to create questions file: %v", err)
	}
	defer file.Close()
	
	combinations := generateCombinations()
	count := 0
	
	for _, combo := range combinations {
		if canMake24(combo) {
			line := fmt.Sprintf("%d,%d,%d,%d\n", combo[0], combo[1], combo[2], combo[3])
			file.WriteString(line)
			count++
		}
	}
	
	fmt.Printf("Generated %d questions that can make 24\n", count)
	return nil
}

// loadQuestions loads questions from the file
func loadQuestions() ([][]int, error) {
	content, err := os.ReadFile("data/24point_questions.txt")
	if err != nil {
		return nil, err
	}
	
	lines := strings.Split(string(content), "\n")
	var questions [][]int
	
	for _, line := range lines {
		if line == "" {
			continue
		}
		
		parts := strings.Split(line, ",")
		if len(parts) != 4 {
			continue
		}
		
		var nums []int
		for _, part := range parts {
			num, err := strconv.Atoi(part)
			if err != nil {
				continue
			}
			nums = append(nums, num)
		}
		
		if len(nums) == 4 {
			questions = append(questions, nums)
		}
	}
	
	return questions, nil
}